﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CoreEx.Database.Query
{
    public interface IExpressionFactory
    {
        ExpressionBase Column(string columnName);
        ExpressionBase Column(string columnPrefix, string columnName);

        ExpressionBase Table(string tableName);
        ExpressionBase Table(string tableName, string alias);        


        ExpressionBase OrderBy(IExpression target);
        ExpressionBase OrderBy(IExpression target, SortDirection direction);

        ExpressionBase Constant(object value);

        ExpressionBase Eq(IExpression leftExpression, IExpression rightExpression);
        ExpressionBase NotEq(IExpression leftExpression, IExpression rightExpression);
        ExpressionBase GreaterThan(IExpression leftExpression, IExpression rightExpression);
        ExpressionBase GreaterOrEqual(IExpression leftExpression, IExpression rightExpression);
        ExpressionBase LessThan(IExpression leftExpression, IExpression rightExpression);
        ExpressionBase LessOrEqual(IExpression leftExpression, IExpression rightExpression);

        ExpressionBase StartsWith(IExpression leftExpression, IExpression rightExpression);
        ExpressionBase Contains(IExpression leftExpression, IExpression rightExpression);
        ExpressionBase EndsWith(IExpression leftExpression, IExpression rightExpression);
        ExpressionBase Or(IExpression leftExpression, IExpression rightExpression);
        ExpressionBase And(IExpression leftExpression, IExpression rightExpression);

        ExpressionBase Count();
        ExpressionBase Count(IExpression target);

        ExpressionBase Sum(IExpression target);


        ExpressionBase Add(IExpression leftExpression, IExpression rightExpression);
        ExpressionBase Subtract(IExpression leftExpression, IExpression rightExpression);
        ExpressionBase Multiply(IExpression leftExpression, IExpression rightExpression);
        ExpressionBase Divide(IExpression leftExpression, IExpression rightExpression);

        SelectQueryExpression Select(IExpression projection);
        SelectQueryExpression Select(Func<IExpressionFactory, IExpression> expression);

        ExpressionBase Alias(IExpression target, string Alias);
        ExpressionBase Alias(Func<IExpressionFactory, IExpression> target, string Alias);

        ExpressionBase Exists<T>(T selectQueryExpression) where T:SelectQueryExpression;
        ExpressionBase Exists<T>(Func<IExpressionFactory, T> target) where T : SelectQueryExpression;

        ExpressionBase List(IEnumerable<IExpression> source);

        ExpressionBase Composite(IExpression leftExpression, IExpression rightExpression);

        ExpressionBase Not(IExpression operand);
        ExpressionBase Distinct(IExpression operand);
        ICaseExpression Case();

        ExpressionBase Join(JoinType joinType, IExpression target, IExpression expression);

        ExpressionBase Union(IExpression leftExpression, IExpression rightExpression);
        ExpressionBase UnionAll(IExpression leftExpression, IExpression rightExpression);
        ExpressionBase Intersect(IExpression leftExpression, IExpression rightExpression);
        ExpressionBase Except(IExpression leftExpression, IExpression rightExpression);
        ExpressionBase In(IExpression target, object[] values);

        ExpressionBase Cast(IExpression target, Type targetType);
    }
}
